﻿/**
* @description  UI widget for simple user click interaction.
*/
package com.foed.buttons {

	import flash.events.MouseEvent;
	import flash.utils.getQualifiedClassName;

	import com.foed.Block;
	import com.foed.UIObject;
	import com.foed.graphic.skins.SkinStates;
	import com.foed.graphic.StyleFormat;
	import com.foed.managers.SoundManager;
	
	public class SimpleButton extends UIObject {
	
		static public const CLASS:String = getQualifiedClassName(SimpleButton);
		static public const GRAPHIC:String = "graphic";

		private var _block:Block;

		/**
		* @description	Initializes component properties.
		*/	
		override protected function init():void {
			super.init();
			_classes.push(SimpleButton.CLASS);
			setEvents();
		}

		/**
		* @description	Creates all necessary nested graphics and components.
		*/	
		override protected function draw():void {
			_block = new Block();
			_block.setSize(width, height);
			_block.setSkin(Block.GRAPHIC, getSkin(GRAPHIC));
			_block.setStyleFormatName(getStyleFormat().name);
			_block.initialize();
			addChild(_block);
		}

		/**
		* @description	Adds event listeners for button events.
		*/	
		private function setEvents():void {
			addEventListener(MouseEvent.ROLL_OVER, onRollOver);
			addEventListener(MouseEvent.ROLL_OUT, onRollOut);
			addEventListener(MouseEvent.MOUSE_DOWN, onPress);
		}
	
		/**
		* @description	Called when the user's mouse rolls off the component.
		*
		* @param  pEvent  Event dispatched by the mouse.
		*/	
		private function onRollOut(pEvent:MouseEvent):void {
			if (!pEvent.buttonDown) rollOutButton();
		}
		
		/**
		* @description	Called when the user's mouse rolls over the component.
		*
		* @param  pEvent  Event dispatched by the mouse.
		*/	
		private function onRollOver(pEvent:MouseEvent):void {
			if (!pEvent.buttonDown) rollOverButton();
		}
		
		/**
		* @description	Called when the user's mouse is over the component when clicked.
		*
		* @param  pEvent  Event dispatched by the mouse.
		*/	
		private function onPress(pEvent:MouseEvent):void {
			stage.addEventListener(MouseEvent.MOUSE_UP, onRelease);
			pressButton();
		}
		
		/**
		* @description	Called when the user's mouse is over the component when clicked, then released.
		*
		* @param  pEvent  Event dispatched by the mouse.
		*/	
		private function onRelease(pEvent:MouseEvent):void {
			stage.removeEventListener(MouseEvent.MOUSE_UP, onRelease);
			if (hitTestPoint(pEvent.stageX, pEvent.stageY)) {
				releaseButton();
			} else {
				releaseOutsideButton();
			}
		}
	
		/**
		* @description	Handles actions and drawing states for the roll out event.
		*/	
		protected function rollOutButton():void {
			state = SkinStates.UP;
		}
		
		/**
		* @description	Handles actions and drawing states for the roll over event.
		*/	
		protected function rollOverButton():void {
			state = SkinStates.OVER;
			SoundManager.getInstance().playSound(this, MouseEvent.ROLL_OVER);
		}
		
		/**
		* @description	Handles actions and drawing states for the press event.
		*/	
		protected function pressButton():void {
			state = SkinStates.DOWN;
			SoundManager.getInstance().playSound(this, MouseEvent.MOUSE_DOWN);
		}
		
		/**
		* @description	Handles actions and drawing states for the release event.
		*/	
		protected function releaseButton():void {
			dispatchEvent(new MouseEvent(MouseEvent.ROLL_OVER));
		}
	
		/**
		* @description	Handles actions and drawing states for the release outside event.
		*/	
		protected function releaseOutsideButton():void {
			dispatchEvent(new MouseEvent(MouseEvent.ROLL_OUT));
		}
			
		/**
		* @description	Sets the width and height of component.
		*
		* @param  pWidth  Width of component.
		* @param  pHeight  Height of component.
		*/	
		override public function setSize(pWidth:Number, pHeight:Number):void {
			super.setSize(pWidth, pHeight);
			if (!_initialized) return; 
			_block.setSize(width, height);
		}

		/**
		* @description	Sets the styleFormat instance to apply to component.
		*
		* @param  pFormat  Instance of StyleFormat to apply to component.
		*/
		override public function setStyleFormat(pStyleFormat:StyleFormat):void {
			super.setStyleFormat(pStyleFormat);
			if (!_initialized) return;
			_block.setStyleFormat(getStyleFormat());
		}
	
		/**
		* @description	Returns the current state of the button, which determines the current drawing of the skin.
		*
		* @returns  The skin state as a string.
		*/
		public function get state():String {
			return _block.state;
		}
	
		/**
		* @description	Sets the current state of the button, which determines the current drawing of the skin.
		*
		* @param  pState  The skin state to change to as a string.
		*/
		public function set state(pState:String):void {
			_block.state = pState;
		}
		
	}

}